
#include "../../Command.h"

#include "../../User.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/Equip.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Battle.h"
#include "../../NLogic/SocialInfo.h"
#include "../../NLogic/Buff.h"
#include "../../NResource/Static.h"

#include <ctime>

namespace ProjectZ { namespace NCommand {

void SendErrorPacket_CS_PVP_MATCH_RES(User * pUser, int16_t res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(res);

	pAck->MakePacket(CMD_SC_QUICK_MATCH_PLAYER);
	pUser->Send(pAck);
}

void SendPacket_CS_PVP_MATCH_RES(User * pUser, User * pOppUser)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().consecutive_win);						// 본인 연승 정보
	*pAck << pOppUser->GetSocialID().c_str();				// 상대방 카카오톡 ID

	if( 1 == pOppUser->GetSocialInfo()->GetData()->_profile_opened )
		*pAck << pOppUser->GetUserInfo().nickname.c_str();		// 상대방 카카오톡 닉네임
	else
		* pAck << static_cast<uint16_t>(0);

	*pAck << pOppUser->GetCharacterInfo().characterseq;		// 캐릭터 Seq
	*pAck << pOppUser->GetUserInfo().profile_url.c_str();	// 상대방 Profile URL
	*pAck << static_cast<uint16_t>(pOppUser->GetCharacterInfo().level);
	*pAck << static_cast<uint8_t>(pOppUser->GetCharacterInfo().classtype);

	// 전투펫 TID
	NLogic::Equip * pOppEquip = pOppUser->GetEquip();
	NLogic::Item * pItem = pOppEquip->GetItem(ITEM_EQUIP_POS_PET);
	if (pItem == NULL)
		*pAck << static_cast<int16_t>(-1);
	else
		*pAck << static_cast<int16_t>(pItem->GetData().tid);

	*pAck << static_cast<int8_t>(-1);		// 길드
	*pAck << static_cast<int16_t>(0);		// ??
	*pAck << pOppUser->GetUserSeq();


	// 사용되고 있는 버프 갯수
	NLogic::Buff * pBuff = pOppUser->GetBuff();
	if (NULL == pBuff)
	{
		::Network::GETPACKETPOOL()->SEND_DEL(pAck);
		DEBUGLOG("SendPacket_CS_PVP_MATCH_RES : pBuff is NULL!!");
		return;
	}

	std::time_t t = std::time(0);  // t is an integer type
	unsigned int nTime = t;

//	* pAck << static_cast<uint8_t>(pBuff->GetDataVector().size());
	* pAck << static_cast<uint8_t>(pBuff->GetActiveBuffCount(nTime));

	std::for_each(pBuff->GetDataVector().begin(), pBuff->GetDataVector().end(), [&](NLogic::Buff::Data * pData) {

		if (pData->u8type == static_cast<int>(NLogic::Buff::BuffType::GUILD))
		{
			* pAck << static_cast<uint8_t>(pData->u8type);
			* pAck << static_cast<uint16_t>(pData->u16skill_tid);
			* pAck << static_cast<uint8_t>(pData->u8skill_level);
			* pAck << static_cast<uint16_t>(pData->s16skill_value);
			* pAck << static_cast<uint16_t>(pData->_regdate);
		}
		else
		{
			if (pData->_regdate < nTime)
			{
				pData->Clear();
			}
			else
			{
				* pAck << static_cast<uint8_t>(pData->u8type);
				* pAck << static_cast<uint16_t>(pData->u16skill_tid);
				* pAck << static_cast<uint8_t>(pData->u8skill_level);
				* pAck << static_cast<uint16_t>(pData->s16skill_value);
				* pAck << static_cast<uint16_t>(pData->_regdate - nTime);
			}
		}
	} );

	pAck->MakePacket(CMD_SC_MATCH_PLAYER);
	pUser->Send(pAck);
}


void Command::CS_PVP_MATCH_RES(User * pUser, ::Network::Packet *pPacket)
{
/*	CS_PVP_MATCH_RES			0x1317
	{
		u8	u8response;					// 0:거절 1: 수락
		u32	party_seq;				/// 파티 시퀀스
	}

	//퀵매치 응답
	SC_QUICK_MATCH_PLAYER		0x1318
	{
		s16	ack;						/// 1:완료 ,  -1 실패
	}*/

	PREPARE_PACKET;

	char response	= 0;
	int spaceSeq	= 0;

	*pPacket >> response >> spaceSeq;

	DEBUGLOG("CS_PVP_MATCH_RES : response=%d", response);

	NLogic::Party * pParty = pUser->GetParty();
	if (NULL == pParty)
	{
		DEBUGLOG("CS_PVP_MATCH_RES : pParty is NUL!!!");
		SendErrorPacket_CS_PVP_MATCH_RES(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Equip * pUserEquip = pUser->GetEquip();
	if (NULL == pUserEquip)
	{
		DEBUGLOG("CS_PVP_MATCH_RES : pUserEquip is NUL!!!");
		SendErrorPacket_CS_PVP_MATCH_RES(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 상대 유저(방장) 검색
	User * pMaster = pParty->GetMaster();

	// 방장이 없는 경우.
	// Timer에 의해 나갔거나, 유저가 접속을 끊은 경우
	if (NULL == pMaster)
	{
		pUser->SetEnumState(User::EnumState::__NONE__);
		pParty->LeaveUser(pUser);

		// 방장이 나간 상태에서 수락을 누른 경우
		if (1 == response)
		{
			SendErrorPacket_CS_PVP_MATCH_RES(pUser, ACK_MATCHING_MASTER_GONE);
		}

		return;
	}

	NLogic::Equip * pMasterEquip = pMaster->GetEquip();
	if (NULL == pMasterEquip)
	{
		DEBUGLOG("CS_PVP_MATCH_RES : pMasterEquip is NUL!!!");
		SendErrorPacket_CS_PVP_MATCH_RES(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Space * pPVPSpace = pMaster->GetSpace();
	if (NULL == pPVPSpace)
	{
		DEBUGLOG("CS_PVP_MATCH_RES : pPVPSpace is NUL!!!");
		SendErrorPacket_CS_PVP_MATCH_RES(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

//	DEBUGLOG("CS_PVP_MATCH_RES : response=%d", response);

	int16_t res = (response == 1) ? ACK_OK : ACK_MATCHING_FAIL;

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << res;

	if (pUser->GetEnumState() == User::EnumState::PVP_QUICK_WAIT)
	{
		pAck->MakePacket(CMD_SC_QUICK_MATCH_PLAYER);
	}
	else if (pUser->GetEnumState() == User::EnumState::PVP_FRIENDLY_WAIT
			|| pUser->GetEnumState() == User::EnumState::PVP_AMITY_WAIT)
	{
		pAck->MakePacket(CMD_SC_PVP_FRIEND_MATCH_REQ);
	}
	pMaster->Send(pAck);

	// 대전 신청 거절
	if (res != ACK_OK)
	{
//		DEBUGLOG("CS_PVP_MATCH_RES : PVP Match reject!! (%s->%s)", pMaster->GetSocialID().c_str(), pUser->GetSocialID().c_str());

		pUser->SetEnumState(User::EnumState::__NONE__);
		pMaster->SetEnumState(User::EnumState::__NONE__);

		// 초대 받은 유저를 파티 유저리스트에서 제거
		pParty->LeaveUser(pUser);

		// 거절하면 방장은 다시 월드로 입장
		pPVPSpace->LeaveUser(pMaster);

		return;
	}

	// 대전 신청 수락
	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("CS_PVP_MATCH_RES : pSpace is NULL!!");
		return;
	}

	// 월드에서 제거하고, PVP 입장
	pSpace->LeaveUser(pUser);
	pPVPSpace->EnterUser(pUser);

	// 유저의 좌표 설정
	pUser->SetCoordinate(PVP_P1_START_X, PVP_P1_START_Y);
	pMaster->SetCoordinate(PVP_P2_START_X, PVP_P2_START_Y, 180);

	pUser->GetBattle()->GetData().bReadyFight = false;
	pMaster->GetBattle()->GetData().bReadyFight = false;

	// 각각 상대방 설정
	pUser->GetBattle()->GetData()._pvpOppUser = pMaster;
	pMaster->GetBattle()->GetData()._pvpOppUser = pUser;

	SendPacket_CS_PVP_MATCH_RES(pUser, pMaster);
	SendPacket_CS_PVP_MATCH_RES(pMaster, pUser);

	pMaster->UpdateLatency();
	pUser->UpdateLatency();

	pPVPSpace->MakePVPResultData(pUser, pMaster);
	pPVPSpace->MakePVPResultData(pMaster, pUser);

	// 전투펫을 장착하고 있다면 스태미너 감소
	if (true == pUserEquip->IsExistItem(ITEM_EQUIP_POS_PET))
	{
		pUserEquip->GetItem(ITEM_EQUIP_POS_PET)->DecreaseBattlepetStamina();
	}

	if (true == pMasterEquip->IsExistItem(ITEM_EQUIP_POS_PET))
	{
		pMasterEquip->GetItem(ITEM_EQUIP_POS_PET)->DecreaseBattlepetStamina();
	}

	// Party 상태 변경
	pParty->SetState(NLogic::Party::State::PVP_ENTERROOM_WAIT);
}

} /*NCommand*/ } /*ProjectZ*/
